CircleCIで AWS CLI v2 を使ってみた
CircleCIからAWSにデプロイするCI/CDを組んでいます。 その際に使っているAWS CLI(v1)をAWS CLI(v2)に変えてみようとなりました。
そこで、CircleCIでAWS CLI(v2)を簡単に使ってみました。本記事では、CircleCIでaws s3 ls
コマンドを実行してバケット一覧を取得します。
本記事よりも、下記のほうが簡単に導入できます。
おすすめの方
- CircleCIからAWSにアクセスしたい方(AssumeRoleを使う)
- CircleCIでAWS CLI(v2)を使いたい方
事前準備
アクセスキーが流出しても被害が最小限になるIAMユーザを作成して使います。
CircleCIで使うIAMユーザとIAMロールを作成
CloudFormationテンプレートを作成する
次のCloudFormationテンプレートをprepare.yaml
として作成します。
sts:ExternalId
には推測されにくい任意の文字列を設定します。これはあとでCircelCIの環境変数に設定します。
AWSTemplateFormatVersion: "2010-09-09" Description: IAM User and IAM Role for CircleCI Resources: # デプロイ用のIAMユーザ DeployUser: Type: AWS::IAM::User Properties: UserName: !Sub circleci-sample-user # デプロイ用のIAMユーザに付与するIAMポリシー(AssumeRoleできる) DeployUserPolicy: Type: AWS::IAM::Policy Properties: PolicyName: !Sub circleci-sample-policy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: sts:AssumeRole Resource: !GetAtt DeployRoleForUser.Arn Users: - !Ref DeployUser # デプロイ用のIAMユーザがAssumeRoleするIAMロール(S3に対するRead権限のみ付与) DeployRoleForUser: Type: AWS::IAM::Role Properties: RoleName: !Sub circleci-sample-role-for-user AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: sts:AssumeRole Principal: AWS: - !GetAtt DeployUser.Arn Condition: StringEquals: sts:ExternalId: any-id-foo-bar Policies: - PolicyName: !Sub circleci-sample-policy-for-user PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - s3:List* Resource: - "*" MaxSessionDuration: 3600 Outputs: DeployRoleArn: Value: !GetAtt DeployRoleForUser.Arn
デプロイする
aws cloudformation deploy \ --template-file prepare.yaml \ --stack-name CircleCI-Sample-Prepare-Stack \ --capabilities CAPABILITY_NAMED_IAM
IAMユーザのアクセスキーを取得する
IAMユーザのアクセスキーを取得します。これはあとでCircelCIの環境変数に設定します。
aws iam create-access-key \ --user-name circleci-sample-user
- AccessKeyId: xxxxxx
- SecretAccessKey: yyyyyy
IAMロールのARNを取得する
作成したIAMロールのARNを取得します。これはあとでCircelCIの環境変数に設定します。
aws cloudformation describe-stacks \ --stack-name CircleCI-Sample-Prepare-Stack \ --query 'Stacks[].Outputs'
- OutputValue: arn:aws:iam::1234567890:role/circleci-sample-role-for-user
AssumeRole用のスクリプトを作成
AssumeRole用に次のスクリプトをassume_role.sh
として作成します。
このスクリプトではIAMユーザがAssumeRoleを行い、指定したIAMロールとして振る舞うための一時的なアクセスキーを取得しています。
#!/usr/bin/env bash set -xeuo pipefail aws_sts_credentials="$(aws sts assume-role \ --role-arn "$AWS_DEPLOY_IAM_ROLE_ARN" \ --role-session-name "$ROLE_SESSION_NAME" \ --external-id "$AWS_DEPLOY_IAM_ROLE_EXTERNAL_ID" \ --duration-seconds 900 \ --query "Credentials" \ --output "json")" cat <<EOT > "aws-env.sh" export AWS_ACCESS_KEY_ID="$(echo $aws_sts_credentials | jq -r '.AccessKeyId')" export AWS_SECRET_ACCESS_KEY="$(echo $aws_sts_credentials | jq -r '.SecretAccessKey')" export AWS_SESSION_TOKEN="$(echo $aws_sts_credentials | jq -r '.SessionToken')" EOT
実行権限を付与しておきます。
chmod 755 assume_role.sh
CircleCIの設定ファイルを作成
.circleci
ディレクトリを作成し、その中にconfig.yml
を作成します。
mkdir .circleci touch .circleci/config.yml
続いて、config.yml
ファイルの中身を記述します。
version: 2.1 executors: my-executor: docker: - image: circleci/python:3.8.5 working_directory: ~/work commands: restore: steps: - restore_cache: key: work-v1-{{ .Revision }} save: steps: - save_cache: paths: - "aws-cli" key: work-v1-{{ .Revision }} install: steps: - run: name: install command: | if [[ ! -d aws-cli ]]; then curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install --install-dir ~/work/aws-cli fi access: steps: - run: name: access command: | export PATH=$PATH:$HOME/work/aws-cli/v2/current/bin aws --version ./assume_role.sh source aws-env.sh aws s3 ls jobs: setup: executor: my-executor steps: - checkout - restore - install - save aws_access: executor: my-executor steps: - checkout - restore - install - save - access workflows: version: 2.1 aws-test-workflow: jobs: - setup: filters: branches: only: - master - aws_access: requires: - setup filters: branches: only: - master
CircleCIの設定
リポジトリのPush
まずはGitHubにリポジトリをPushしておきます。
git push origin master
プロジェクトの設定
CircleCIにログインし、先ほどのリポジトリの「Set Up Project」を選択してプロジェクト設定を行います。
環境変数の設定
Pipelineが動き出すので、右上にある「Project Settings」を選択します。
「Environment Variables」を選択し、環境変数の設定を行います。 コピペ時に空白が混ざらないように注意してください(たまに良くある)。
Name | Value |
---|---|
AWS_ACCESS_KEY_ID | 取得したAccessKeyId |
AWS_SECRET_ACCESS_KEY | 取得したSecretAccessKey |
AWS_DEPLOY_IAM_ROLE_ARN | 取得したIAMロールのARN |
AWS_DEPLOY_IAM_ROLE_EXTERNAL_ID | sts:ExternalIdで設定した値 |
AWS_DEFAULT_REGION | ap-northeast-1 |
AWS_DEFAULT_OUTPUT | json |
ROLE_SESSION_NAME | CircleCI |
いざ、実行!
既に動いて失敗しているPipelineがあると思うので、「Rerun」します。
しばらくすると、成功しました!
Jobの詳細を確認すると、S3バケットの一覧がバッチリ取得できています!
片付け
実験終了後、作成したIAMユーザなどを削除しておきます。使わないIAMユーザ(アクセスキー有)を放置するのは、セキュリティ的によろしくないからです。
aws cloudformation delete-stack \ --stack-name CircleCI-Sample-Prepare-Stack
さいごに
CircleCIでAWS CLI(v2)を使ってみました。 本記事では直接インストールしましたが、Dockerイメージを使う方式でも対応できそうです。